//
//  TCPProxyServer.swift
//  Tunnel
//
//  Created by blackhat on 2023/10/13.
//

import Foundation
import NIO
import CLwIP


class TCPProxyServer: NSObject {
    
    // tun连接器
    let tunHub: LWIPTunHub
    // 本地的socket代理
    let group = MultiThreadedEventLoopGroup(numberOfThreads: System.coreCount)
    
    let bootstrap: ServerBootstrap
    
    public static let shared: TCPProxyServer = {
        let instance = TCPProxyServer()
        return instance
    }()

    override init() {
        tunHub = LWIPTunHub()
        defer {
            do {
                try group.syncShutdownGracefully()
            } catch {
                print("Error shutting down event loop group: \(error)")
            }
        }
        let lwipEventLoop: EventLoop = tunHub.getEventLoop()
        // 远端请求的代理,使用swiftnio
        bootstrap = ServerBootstrap(group: group)
            .serverChannelOption(ChannelOptions.backlog, value: 256)
            .serverChannelOption(ChannelOptions.socket(SocketOptionLevel(SOL_SOCKET), SO_REUSEADDR), value: 1)
            .serverChannelInitializer { channel in
                channel.pipeline.addHandler(LWIPHandler(lwipEventLoop: lwipEventLoop))
            }
            .childChannelInitializer { channel in
                channel.pipeline.addHandler(ProxyHandler())
            }
            .childChannelOption(ChannelOptions.socket(IPPROTO_TCP, TCP_NODELAY), value: 1)
            .childChannelOption(ChannelOptions.socket(SocketOptionLevel(SOL_SOCKET), SO_REUSEADDR), value: 1)
            .childChannelOption(ChannelOptions.maxMessagesPerRead, value: 16)
            .childChannelOption(ChannelOptions.recvAllocator, value: AdaptiveRecvByteBufferAllocator(minimum: 64, initial: 1024, maximum: 65536))
        super.init()
    }
    
    public func run() {
        do {
            let serverChannel = try self.bootstrap.bind(host: "localhost", port: 8888).wait()
            print("Server running on:", serverChannel.localAddress!)
            try serverChannel.closeFuture.wait()
        } catch {
            print("Error starting server: \(error)")
        }
    }

}

